package com.eight.lotteryservice.config;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eight.lotteryservice.controller.LotteryController;
import com.eight.lotteryservice.entity.RedGame;
import com.eight.lotteryservice.entity.RedGameProduct;
import com.eight.lotteryservice.entity.RedProduct;
import com.eight.lotteryservice.mapper.RedGameMapper;
import com.eight.lotteryservice.mapper.RedGameProductMapper;
import com.eight.lotteryservice.mapper.RedProductMapper;
import com.eight.lotteryservice.utils.RedisUtil;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

@Configuration      //1.主要用于标记配置类，兼备Component的效果。
@EnableScheduling   // 2.开启定时任务
public class SaticScheduleTask {

    @Resource
    RedGameMapper redGameMapper;
    @Resource
    RedProductMapper redProductMapper;
    @Resource
    RedGameProductMapper redGameProductMapper;
    @Resource
    private RedisUtil redisUtil;

    private final static Logger log = LoggerFactory.getLogger(SaticScheduleTask.class);

    //3.添加定时任务
    @Scheduled(cron = "0 */1 * * * ?")
    //或直接指定时间间隔，例如：5秒
//    @Scheduled(fixedRate=5000)
    private void configureTasks() {

//        System.err.println("执行静态定时任务时间: " + LocalDateTime.now());
//        log.info("configureTasks：启动预热：");
//        todo 开启预热
//        execute();
    }

    public void execute() {
        //当前时间
        Date now = new Date();
//       1。 开始时间大于当前时间
//       2. 小雨等于 当前时间+1min
        //查询将来1分钟内要开始的活动
        QueryWrapper<RedGame> queryWrapper = new QueryWrapper<>();
        queryWrapper.ge("starttime", now);
        queryWrapper.le("starttime", DateUtils.addMinutes(now, 1));
        List<RedGame> list = redGameMapper.selectList(queryWrapper);
//        测试用
//        List<RedGame> list = redGameMapper.selectList(null);
        log.info("game list :"+list);
        if (list.size() == 0) {
            //没有查到要开始的活动
            log.info("game list scan : size = 0");
            return;
        }
        log.info("game list scan : size = {}", list.size());
        //有相关活动数据，则将活动数据预热，进redis
        // 只有一个场次，不可能同一时间有多个场次
        RedGame game = list.get(0);

        //活动开始时间
        long start = game.getStarttime().getTime();
        //活动结束时间
        long end = game.getEndtime().getTime();
        //计算活动结束时间到现在还有多少秒，作为redis key过期时间
        long expire = (end - now.getTime()) / 1000;

        redisUtil.set("_expire",expire,expire);
//            long expire = -1; //永不过期
        //活动持续时间（ms）
        long duration = end - start;

        int now_rounds = game.getRound();
//      Redis 设置 k:userid_rounds v:now_rounds
        //活动基本信息
        game.setStatus(true);
//      redis  设置get
        redisUtil.set("_game",game);
//      redisUtil.set(RedisKeys.INFO+game.getId(),game,-1);
        log.info("load game info:{},{},{},{}", game.getId(), game.getTitle(), game.getStarttime(), game.getEndtime());
        //活动奖品信息
        /**
         * 这里可以从只需要三个奖品
         */
        //  1. 查询一二三等奖的份数
        //  num_1,num_2,num_3
//        QueryWrapper<RedProduct> productQueryWrapper = new QueryWrapper<>();
//        /**
//         * 这里要后续和game关联
//         */
//        List<RedProduct> products = redProductMapper.selectList(productQueryWrapper);
        QueryWrapper<RedGameProduct> gameProductQueryWrapper = new QueryWrapper<>();
        int gameid = game.getId();
        gameProductQueryWrapper.eq("gameid",gameid);
        List<RedGameProduct> redGameProducts = redGameProductMapper.selectList(gameProductQueryWrapper);

        List<Long> tokenList = new ArrayList();
        redGameProducts.forEach(redGameProduct -> {
//            Integer gameid = redGameProduct.getGameid();
            Integer product_id = redGameProduct.getProductid();
            QueryWrapper<RedProduct> productQueryWrapper = new QueryWrapper<>();
            productQueryWrapper.eq("id", product_id);
            List<RedProduct> products = redProductMapper.selectList(productQueryWrapper);
            products.forEach(product ->{
                log.info("奖品:"+product.getName());
                log.info("个数:"+redGameProduct.getAmount());
                for( int i =0 ; i < redGameProduct.getAmount() ;i++){
                    long rnd = start + new Random().nextInt((int) duration);
                    //为什么乘1000，再额外加一个随机数呢？ - 防止时间段奖品多时重复
                    //记得取令牌判断时间时，除以1000，还原真正的时间戳
                    // token是时间错
                    long token = rnd * 1000 + new Random().nextInt(999);
                    //将令牌放入令牌桶
                    tokenList.add(token);
                    //以令牌做key，对应的商品为value，创建redis缓存
//                   令牌key：商品value
//                    log.info("token -> game : {} -> {}", token / 1000, redProductMapper.selectById(product.getId()).getName());
                    //token到实际奖品之间建立映射关系
                    /**
                     * redis token和奖品的关系
                     * key:
                     * value: reProduct
                     */
                    redisUtil.set(game.getId() +"_"+token,product,expire);

                }

            });
        });
        //  2. products.push(Products(1)*num1)
        // products.push(Products(2)*num2)
        // products.push(Products(3)*num3)
        // List<CardProductDto> products = gameLoadMapper.getByGameId(game.getId());

//        Map<Integer,CardProduct> productMap = new HashMap<>(products.size());
//        products.forEach(p -> productMap.put(p.getId(),p));
//        log.info("load product type:{}",productMap.size());
//
//        //奖品数量等配置信息
//        CardGameProductExample productExample = new CardGameProductExample();
//        productExample.createCriteria().andGameidEqualTo(game.getId());
//        List<CardGameProduct> gameProducts = gameProductMapper.selectByExample(productExample);
//        log.info("load bind product:{}",gameProducts.size());

        //令牌桶


        //排序后放入redis队列
        Collections.sort(tokenList);
        log.info("load tokens:{}", tokenList);

        // 从右侧压入队列，从左到右，时间戳逐个增大
        redisUtil.rightPushAll(RedisKeys.BUCKET + game.getId(),tokenList);
        redisUtil.expire(RedisKeys.BUCKET + game.getId(),expire);

//        List<>redisUtil.get(RedisKeys.TOKENS + game.getId());

        /**
         * 不需要策略？
         */
        //奖品策略配置信息
//        CardGameRulesExample rulesExample = new CardGameRulesExample();
//        rulesExample.createCriteria().andGameidEqualTo(game.getId());
//        List<CardGameRules> rules = gameRulesMapper.selectByExample(rulesExample);
//        //遍历策略，存入redis hset
//        rules.forEach(r -> {
//            redisUtil.hset(RedisKeys.MAXGOAL +game.getId(),r.getUserlevel()+"",r.getGoalTimes());
//            redisUtil.hset(RedisKeys.MAXENTER +game.getId(),r.getUserlevel()+"",r.getEnterTimes());
//            log.info("load rules:level={},enter={},goal={}",r.getUserlevel(),r.getEnterTimes(),r.getGoalTimes());
//        });
//        redisUtil.expire(RedisKeys.MAXGOAL +game.getId(),expire);
//        redisUtil.expire(RedisKeys.MAXENTER +game.getId(),expire);


        //活动状态变更为已预热，禁止管理后台再随便变动
        game.setStatus(true);
        redGameMapper.updateById(game);
//}

    }
}
